<html>
<head>
<title>Decrypting PKCS #8 and OpenSSL Private Keys with Java</title>
<style type="text/css">
h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
h1 { float: left; color: red; }
b.n { font-family: arial; font-weight: bold; }
span.hl { color: white; background-color: green; }
div.nav { float: left; margin-left: 20px; font-weight: bold; }
.nav a, .nav span { padding: 0 5px; }
.nav a { color: blue; }
li.top { margin-top: 10px; }
ul.openssl { float: left; width: 100px; margin-top: 8px; }
ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
</style>
</head>
<body>
<h1>not-yet-commons-ssl</h1>
<div class="nav">
<a href="index.html">main</a> |
<a href="ssl.html">ssl</a> |
<span class="hl" href="pkcs8.html">pkcs8</span> |
<a href="pbe.html">pbe</a> |
<a href="rmi.html">rmi</a> |
<a href="utilities.html">utilities</a> |
<a href="source.html">source</a> |
<a href="javadocs/">javadocs</a> |
<a href="download.html">download</a>
</div>
<br clear="all"/>
<hr/>
<h2>PKCS #8 / OpenSSL Encrypted Keys</em></h2>
<br/>
<h3>Java 1.3 Compatible! (with <a href="http://java.sun.com/products/jce/index-122.html">jce1_2_2.jar</a>) (or <a href="http://bouncycastle.org/latest_releases.html">bcprov-jdk13.jar</a>)</h3>
<p>Commons-SSL includes support for extracting private keys from PKCS #8 files.
We also support the OpenSSL formats ("traditional SSLeay").  The private keys can be in PEM (base64)
or DER (raw ASN.1 - a binary format).
</p>
<p>The code works with Java 1.3 (+JCE), 1.4, 5.0, 6.0, but not all of the ciphers and hashes are available
until Java 5.0 (unless you use BouncyCastle).  Fortunately the most common formats [OpenSSL MD5 with 3DES], [PKCS #8 V1.5 MD5 with DES], [PKCS #8 V2.0 HmacSHA1 with 3DES]
work with all versions of Java, including Java 1.3.</p>
<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>pkcs8 example:</b></u>

FileInputStream in = new FileInputStream( "/path/to/pkcs8_private_key.der" );

<em style="color: green;">// If the provided InputStream is encrypted, we need a password to decrypt</em>
<em style="color: green;">// it. If the InputStream is not encrypted, then the password is ignored</em>
<em style="color: green;">// (can be null).  The InputStream can be DER (raw ASN.1) or PEM (base64).</em>
PKCS8Key pkcs8 = new PKCS8Key( in, "changeit".toCharArray() );

<em style="color: green;">// If an unencrypted PKCS8 key was provided, then this actually returns</em>
<em style="color: green;">// exactly what was originally passed in (with no changes).  If an OpenSSL</em>
<em style="color: green;">// key was provided, it gets reformatted as PKCS #8 first, and so these</em>
<em style="color: green;">// bytes will still be PKCS #8, not OpenSSL.</em>
byte[] decrypted = pkcs8.getDecryptedBytes();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec( decrypted );

<em style="color: green;">// A Java PrivateKey object is born.</em>
PrivateKey pk = null;
if ( pkcs8.isDSA() )
{
  pk = KeyFactory.getInstance( "DSA" ).generatePrivate( spec );
}
else if ( pkcs8.isRSA() )
{
  pk = KeyFactory.getInstance( "RSA" ).generatePrivate( spec );
}

<em style="color: green;">// For lazier types:</em>
pk = pkcs8.getPrivateKey();
</pre>
<br clear="all"/>
<p>Both RSA and DSA keys are supported.  Here is a list of supported formats:</p>
<ul>
<li class="top"><b>OpenSSL "Traditional SSLeay Compatible Format"</b><ul>
<li>Unencrypted PEM or DER</li>
<li>Encrypted PEM:<br/>
<ul class="openssl"><li>des</li><li>des2</li><li>des3</li><li>blowfish</li></ul>
<ul class="openssl"><li>aes128</li><li>aes192</li><li>aes256</li></ul>
<ul class="openssl"><li>rc2-40</li><li>rc2-64</li><li>rc2-128</li></ul>
<br clear="all"/>
<dl style="margin-top: 1em; width: 600px;"><dt>Note:</dt><dd>OpenSSL "traditional SSLeay" format does not allow encrypted keys to be encoded in DER.  Only
unencrypted keys can be encoded in DER.</dd></dl></li>
</ul>
</li>
<li class="top"><b>PKCS #8 (Unencrypted)</b>
<ul><li>PEM or DER</li></ul></li>
<li class="top"><b>PKCS #8 with PKCS #5 Version 1.5 Encryption</b>
<ul><li>PEM or DER:
<ul class="pkcs8">
<li>MD2&nbsp;with&nbsp;DES</li>
<li>MD2&nbsp;with&nbsp;RC2-64</li>
</ul>
<ul class="pkcs8">
<li>MD5&nbsp;with&nbsp;DES</li>
<li>MD5&nbsp;with&nbsp;RC2-64</li>
</ul>
<ul class="pkcs8">
<li>SHA1&nbsp;with&nbsp;DES</li>
<li>SHA1&nbsp;with&nbsp;RC2-64</li>
</ul>
<br clear="all"/>
</li></ul></li>
<li class="top"><b>PKCS #8 with PKCS #5 Version 1.5 Encryption and PKCS #12 Key Derivation</b>
<ul><li>PEM or DER:
<ul class="pkcs8">
<li>SHA1&nbsp;with&nbsp;3DES</li>
<li>SHA1&nbsp;with&nbsp;2DES</li>
</ul>
<ul class="pkcs8">
<li>SHA1&nbsp;with&nbsp;RC2-128</li>
<li>SHA1&nbsp;with&nbsp;RC2-40</li>
</ul>
<ul class="pkcs8">
<li>SHA1&nbsp;with&nbsp;RC4-128</li>
<li>SHA1&nbsp;with&nbsp;RC4-40</li>
</ul>
<br clear="all"/>
</li></ul></li>
<li class="top"><b>PKCS #8 with PKCS #5 Version 2.0 Encryption and HmacSHA1</b>
<ul><li>PEM or DER:
<ul class="pkcs8">
<li>DES</li>
<li>3DES</li>
<li>Blowfish</li>
</ul>
<ul class="pkcs8">
<li>AES-128</li>
<li>AES-192</li>
<li>AES-256</li>
</ul>
<ul class="pkcs8">
<li>RC2-40</li>
<li>RC2-64</li>
<li>RC2-128</li>
</ul>
<br clear="all"/>
</li></ul></li></ul>
<hr/>
<p>
Here are links to the raw samples and test results:
<ol>
<li><a href="samples/rsa_result.html">2048 Bit RSA</a></li>
<li><a href="samples/dsa_result.html">2048 Bit DSA</a></li>
</ol>
</p>
<p>The samples were all generated using OpenSSL's
<code>rsa</code>, <code>genrsa</code>, <code>dsa</code>, <code>gendsa</code>, <code>dsaparam</code>
and <code>pkcs8</code> commands.  We're curious to know if
PKCS #8 keys created by other programs will also work, but OpenSSL is all we have to play
with at the moment.</p>
<p>The password to decrypt the samples is always "changeit", and they all have the same RSA or DSA
key.</p>

</body>
</html>
